﻿using System;
using System.Linq;
using System.Text;
using BattleFury.Lib.Managers;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace BattleFury.Lib.Input
{
	public class KeyboardManager
		: Manager
	{
		private KeyboardState _previous;
		private KeyboardState _current;

		private DateTime _previousUpdate = DateTime.Now;

		public int MustPass = 200;
		public string TextInput { get; set; }

		public override void Update(GameTime gameTime)
		{
			if (!IsEnabled) return;

			_previous = _current;
			_current = Keyboard.GetState();

			var input = ConvertToString(_current.GetPressedKeys());
			var prevInput = ConvertToString(_previous.GetPressedKeys());

			var now = DateTime.Now;
			var time = MustPass;
			if (input == "\b") time -= 25;
			if (now.Subtract(_previousUpdate).Milliseconds >= time)
			{
				foreach (var x in input)
				{
					if (x == '\b')
					{
						if (TextInput.Length >= 1) TextInput = TextInput.Remove(TextInput.Length - 1, 1);
					}
					else
					{
						TextInput += x;
					}
					if (!string.IsNullOrEmpty(input)) _previousUpdate = now;
				}
			}
		}

		public bool IsKeyPressed(Keys key)
		{
			return _current.IsKeyDown(key) && _previous.IsKeyUp(key);
		}

		public bool IsKeyHeld(Keys key)
		{
			return _current.IsKeyDown(key) && _previous.IsKeyDown(key);
		}

		public string ConvertToString(Keys[] keys)
		{
			var output = new StringBuilder();
			var usesShift = (keys.Contains(Keys.LeftShift) || keys.Contains(Keys.RightShift));

			for (var i = 0; i < keys.Length; i++)
			{
				var key = keys[i];
				if (_previous.IsKeyUp(key)) continue;

				if (key >= Keys.A && key <= Keys.Z) output.Append(key.ToString());
				else if (key >= Keys.NumPad0 && key <= Keys.NumPad9) output.Append((key - Keys.NumPad0).ToString());
				else if (key >= Keys.D0 && key <= Keys.D9)
				{
					var num = ((key - Keys.D0)).ToString();
					if (usesShift)
					{
						switch (num)
						{
							case "1":
								num = "!";
								break;
							case "2":
								num = "@";
								break;
							case "3":
								num = "#";
								break;
							case "4":
								num = "$";
								break;
							case "5":
								num = "%";
								break;
							case "6":
								num = "^";
								break;
							case "7":
								num = "&";
								break;
							case "8":
								num = "*";
								break;
							case "9":
								num = "(";
								break;
							case "0":
								num = ")";
								break;
							default:
								break;
						}
					}
					output.Append(num);
				}
				else if (key == Keys.OemPeriod) output.Append(".");
				else if (key == Keys.OemTilde) output.Append("`");
				else if (key == Keys.Space) output.Append(" ");
				else if (key == Keys.OemMinus) output.Append("-");
				else if (key == Keys.OemPlus) output.Append("+");
				else if (key == Keys.OemQuestion && usesShift) output.Append("?");
				else if (key == Keys.Back) output.Append("\b");

				if (!usesShift)
				{
					var rawOutput = output.ToString();
					output.Clear();
					if (!string.IsNullOrEmpty(rawOutput))
					{
						output.Append(rawOutput.Substring(0, rawOutput.Length - 1));
						output.Append(rawOutput.Substring(rawOutput.Length - 1, 1).ToLower());
					}
				}
			}
			return output.ToString();
		}
	}
}